<!doctype html><html lang="en">
 <head>
  <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
  <title>Motion Sensors Explainer</title>
  <meta content="NOTE" name="w3c-status">
  <link href="https://www.w3.org/StyleSheets/TR/2016/W3C-NOTE" rel="stylesheet">
  <link href="https://www.w3.org/2008/site/images/favicon.ico" rel="icon">
  <link href="https://www.w3.org/TR/motion-sensors/" rel="canonical">
<style>
table {
  border-collapse: collapse;
  border-spacing: 0px;
}
table, th, td {
  padding: 5px;
  border: 1px solid black;
}
</style>
<style>/* style-md-lists */

/* This is a weird hack for me not yet following the commonmark spec
   regarding paragraph and lists. */
[data-md] > :first-child {
    margin-top: 0;
}
[data-md] > :last-child {
    margin-bottom: 0;
}</style>
<style>/* style-selflinks */

.heading, .issue, .note, .example, li, dt {
    position: relative;
}
a.self-link {
    position: absolute;
    top: 0;
    left: calc(-1 * (3.5rem - 26px));
    width: calc(3.5rem - 26px);
    height: 2em;
    text-align: center;
    border: none;
    transition: opacity .2s;
    opacity: .5;
}
a.self-link:hover {
    opacity: 1;
}
.heading > a.self-link {
    font-size: 83%;
}
li > a.self-link {
    left: calc(-1 * (3.5rem - 26px) - 2em);
}
dfn > a.self-link {
    top: auto;
    left: auto;
    opacity: 0;
    width: 1.5em;
    height: 1.5em;
    background: gray;
    color: white;
    font-style: normal;
    transition: opacity .2s, background-color .2s, color .2s;
}
dfn:hover > a.self-link {
    opacity: 1;
}
dfn > a.self-link:hover {
    color: black;
}

a.self-link::before            { content: "¶"; }
.heading > a.self-link::before { content: "§"; }
dfn > a.self-link::before      { content: "#"; }</style>
<style>/* style-counters */

body {
    counter-reset: example figure issue;
}
.issue {
    counter-increment: issue;
}
.issue:not(.no-marker)::before {
    content: "Issue " counter(issue);
}

.example {
    counter-increment: example;
}
.example:not(.no-marker)::before {
    content: "Example " counter(example);
}
.invalid.example:not(.no-marker)::before,
.illegal.example:not(.no-marker)::before {
    content: "Invalid Example" counter(example);
}

figcaption {
    counter-increment: figure;
}
figcaption:not(.no-marker)::before {
    content: "Figure " counter(figure) " ";
}</style>
<style>/* style-autolinks */

.css.css, .property.property, .descriptor.descriptor {
    color: #005a9c;
    font-size: inherit;
    font-family: inherit;
}
.css::before, .property::before, .descriptor::before {
    content: "‘";
}
.css::after, .property::after, .descriptor::after {
    content: "’";
}
.property, .descriptor {
    /* Don't wrap property and descriptor names */
    white-space: nowrap;
}
.type { /* CSS value <type> */
    font-style: italic;
}
pre .property::before, pre .property::after {
    content: "";
}
[data-link-type="property"]::before,
[data-link-type="propdesc"]::before,
[data-link-type="descriptor"]::before,
[data-link-type="value"]::before,
[data-link-type="function"]::before,
[data-link-type="at-rule"]::before,
[data-link-type="selector"]::before,
[data-link-type="maybe"]::before {
    content: "‘";
}
[data-link-type="property"]::after,
[data-link-type="propdesc"]::after,
[data-link-type="descriptor"]::after,
[data-link-type="value"]::after,
[data-link-type="function"]::after,
[data-link-type="at-rule"]::after,
[data-link-type="selector"]::after,
[data-link-type="maybe"]::after {
    content: "’";
}

[data-link-type].production::before,
[data-link-type].production::after,
.prod [data-link-type]::before,
.prod [data-link-type]::after {
    content: "";
}

[data-link-type=element],
[data-link-type=element-attr] {
    font-family: Menlo, Consolas, "DejaVu Sans Mono", monospace;
    font-size: .9em;
}
[data-link-type=element]::before { content: "<" }
[data-link-type=element]::after  { content: ">" }

[data-link-type=biblio] {
    white-space: pre;
}</style>
<style>/* style-dfn-panel */

.dfn-panel {
    position: absolute;
    z-index: 35;
    height: auto;
    width: -webkit-fit-content;
    width: fit-content;
    max-width: 300px;
    max-height: 500px;
    overflow: auto;
    padding: 0.5em 0.75em;
    font: small Helvetica Neue, sans-serif, Droid Sans Fallback;
    background: #DDDDDD;
    color: black;
    border: outset 0.2em;
}
.dfn-panel:not(.on) { display: none; }
.dfn-panel * { margin: 0; padding: 0; text-indent: 0; }
.dfn-panel > b { display: block; }
.dfn-panel a { color: black; }
.dfn-panel a:not(:hover) { text-decoration: none !important; border-bottom: none !important; }
.dfn-panel > b + b { margin-top: 0.25em; }
.dfn-panel ul { padding: 0; }
.dfn-panel li { list-style: inside; }
.dfn-panel.activated {
    display: inline-block;
    position: fixed;
    left: .5em;
    bottom: 2em;
    margin: 0 auto;
    max-width: calc(100vw - 1.5em - .4em - .5em);
    max-height: 30vh;
}

.dfn-paneled { cursor: pointer; }
</style>
<style>/* style-syntax-highlighting */

.highlight:not(.idl) { background: hsl(24, 20%, 95%); }
code.highlight { padding: .1em; border-radius: .3em; }
pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; }
c-[a] { color: #990055 } /* Keyword.Declaration */
c-[b] { color: #990055 } /* Keyword.Type */
c-[c] { color: #708090 } /* Comment */
c-[d] { color: #708090 } /* Comment.Multiline */
c-[e] { color: #0077aa } /* Name.Attribute */
c-[f] { color: #669900 } /* Name.Tag */
c-[g] { color: #222222 } /* Name.Variable */
c-[k] { color: #990055 } /* Keyword */
c-[l] { color: #000000 } /* Literal */
c-[m] { color: #000000 } /* Literal.Number */
c-[n] { color: #0077aa } /* Name */
c-[o] { color: #999999 } /* Operator */
c-[p] { color: #999999 } /* Punctuation */
c-[s] { color: #a67f59 } /* Literal.String */
c-[t] { color: #a67f59 } /* Literal.String.Single */
c-[u] { color: #a67f59 } /* Literal.String.Double */
c-[cp] { color: #708090 } /* Comment.Preproc */
c-[c1] { color: #708090 } /* Comment.Single */
c-[cs] { color: #708090 } /* Comment.Special */
c-[kc] { color: #990055 } /* Keyword.Constant */
c-[kn] { color: #990055 } /* Keyword.Namespace */
c-[kp] { color: #990055 } /* Keyword.Pseudo */
c-[kr] { color: #990055 } /* Keyword.Reserved */
c-[ld] { color: #000000 } /* Literal.Date */
c-[nc] { color: #0077aa } /* Name.Class */
c-[no] { color: #0077aa } /* Name.Constant */
c-[nd] { color: #0077aa } /* Name.Decorator */
c-[ni] { color: #0077aa } /* Name.Entity */
c-[ne] { color: #0077aa } /* Name.Exception */
c-[nf] { color: #0077aa } /* Name.Function */
c-[nl] { color: #0077aa } /* Name.Label */
c-[nn] { color: #0077aa } /* Name.Namespace */
c-[py] { color: #0077aa } /* Name.Property */
c-[ow] { color: #999999 } /* Operator.Word */
c-[mb] { color: #000000 } /* Literal.Number.Bin */
c-[mf] { color: #000000 } /* Literal.Number.Float */
c-[mh] { color: #000000 } /* Literal.Number.Hex */
c-[mi] { color: #000000 } /* Literal.Number.Integer */
c-[mo] { color: #000000 } /* Literal.Number.Oct */
c-[sb] { color: #a67f59 } /* Literal.String.Backtick */
c-[sc] { color: #a67f59 } /* Literal.String.Char */
c-[sd] { color: #a67f59 } /* Literal.String.Doc */
c-[se] { color: #a67f59 } /* Literal.String.Escape */
c-[sh] { color: #a67f59 } /* Literal.String.Heredoc */
c-[si] { color: #a67f59 } /* Literal.String.Interpol */
c-[sx] { color: #a67f59 } /* Literal.String.Other */
c-[sr] { color: #a67f59 } /* Literal.String.Regex */
c-[ss] { color: #a67f59 } /* Literal.String.Symbol */
c-[vc] { color: #0077aa } /* Name.Variable.Class */
c-[vg] { color: #0077aa } /* Name.Variable.Global */
c-[vi] { color: #0077aa } /* Name.Variable.Instance */
c-[il] { color: #000000 } /* Literal.Number.Integer.Long */
</style>
 <body class="h-entry">
  <div class="head">
   <p data-fill-with="logo"><a class="logo" href="https://www.w3.org/"> <img alt="W3C" height="48" src="https://www.w3.org/StyleSheets/TR/2016/logos/W3C" width="72"> </a> </p>
   <h1 class="p-name no-ref" id="title">Motion Sensors Explainer</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">W3C Note, <time class="dt-updated" datetime="1970-01-01">1 January 1970</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="https://www.w3.org/TR/1970/NOTE-motion-sensors-19700101/">https://www.w3.org/TR/1970/NOTE-motion-sensors-19700101/</a>
     <dt>Latest published version:
     <dd><a href="https://www.w3.org/TR/motion-sensors/">https://www.w3.org/TR/motion-sensors/</a>
     <dt>Editor's Draft:
     <dd><a href="https://w3c.github.io/motion-sensors/">https://w3c.github.io/motion-sensors/</a>
     <dt>Version History:
     <dd><a href="https://github.com/w3c/motion-sensors/commits/gh-pages/index.bs">https://github.com/w3c/motion-sensors/commits/gh-pages/index.bs</a>
     <dt>Feedback:
     <dd><span><a href="mailto:public-device-apis@w3.org?subject=%5Bmotion-sensors%5D%20YOUR%20TOPIC%20HERE">public-device-apis@w3.org</a> with subject line “<kbd>[motion-sensors] <i data-lt>… message topic …</i></kbd>” (<a href="https://lists.w3.org/Archives/Public/public-device-apis/" rel="discussion">archives</a>)</span>
     <dt class="editor">Editors:
     <dd class="editor p-author h-card vcard" data-editor-id="57705"><a class="p-name fn u-url url" href="https://intel.com/">Kenneth Rohde Christiansen</a> (<span class="p-org org">Intel Corporation</span>)
     <dd class="editor p-author h-card vcard" data-editor-id="78335"><a class="p-name fn u-url url" href="http://intel.com/">Alexander Shalamov</a> (<span class="p-org org">Intel Corporation</span>)
     <dt>Bug Reports:
     <dd><a href="https://www.github.com/w3c/motion-sensors/issues/new">via the w3c/motion-sensors repository on GitHub</a>
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <p class="copyright" data-fill-with="copyright"><a href="https://www.w3.org/Consortium/Legal/ipr-notice#Copyright">Copyright</a> © 1970 <a href="https://www.w3.org/"><abbr title="World Wide Web Consortium">W3C</abbr></a><sup>®</sup> (<a href="https://www.csail.mit.edu/"><abbr title="Massachusetts Institute of Technology">MIT</abbr></a>, <a href="https://www.ercim.eu/"><abbr title="European Research Consortium for Informatics and Mathematics">ERCIM</abbr></a>, <a href="https://www.keio.ac.jp/">Keio</a>, <a href="https://ev.buaa.edu.cn/">Beihang</a>). W3C <a href="http://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer">liability</a>, <a href="https://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks">trademark</a> and <a href="https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document" rel="license">permissive document license</a> rules apply. </p>
   <hr title="Separator for header">
  </div>
  <div class="p-summary" data-fill-with="abstract">
   <h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2>
   <p>This explainer is an introduction to low-level and high-level motion sensors,

  their relationship, inner workings and common use-cases. Common cases of event
  filtering and sensor fusion are introduced with examples, showing how to apply
  that on sensors following the Generic Sensor API specification.</p>
  </div>
  <h2 class="no-num no-toc no-ref heading settled" id="sotd"><span class="content">Status of this document</span></h2>
  <div data-fill-with="status">
   <p></p>
  </div>
  <div data-fill-with="at-risk"></div>
  <nav data-fill-with="table-of-contents" id="toc">
   <h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
   <ol class="toc" role="directory">
    <li><a href="#intro"><span class="secno">1</span> <span class="content">Introduction</span></a>
    <li><a href="#security-and-privacy"><span class="secno">2</span> <span class="content">Security and Privacy Considerations</span></a>
    <li>
     <a href="#low-level-sensors"><span class="secno">3</span> <span class="content">Low-level Sensors</span></a>
     <ol class="toc">
      <li><a href="#accelerometer-sensor"><span class="secno">3.1</span> <span class="content">Accelerometer</span></a>
      <li><a href="#gyroscope-sensor"><span class="secno">3.2</span> <span class="content">Gyroscope</span></a>
      <li><a href="#magnetometer-sensor"><span class="secno">3.3</span> <span class="content">Magnetometer</span></a>
     </ol>
    <li>
     <a href="#highlevel-sensors"><span class="secno">4</span> <span class="content">High-level Sensors</span></a>
     <ol class="toc">
      <li><a href="#fusion-sensors"><span class="secno">4.1</span> <span class="content">Common fusion sensors</span></a>
      <li>
       <a href="#pass-filters"><span class="secno">4.2</span> <span class="content">Low and high pass filters</span></a>
       <ol class="toc">
        <li><a href="#low-pass-filters"><span class="secno">4.2.1</span> <span class="content">Low-pass filter</span></a>
        <li><a href="#high-pass-filters"><span class="secno">4.2.2</span> <span class="content">High-pass filter</span></a>
       </ol>
      <li><a href="#absolute-orientation"><span class="secno">4.3</span> <span class="content">Absolute Orientation Sensor</span></a>
      <li><a href="#geomagnetic-orientation"><span class="secno">4.4</span> <span class="content">Geomagnetic Orientation Sensor</span></a>
      <li>
       <a href="#relative-orientation"><span class="secno">4.5</span> <span class="content">Relative Orientation Sensor</span></a>
       <ol class="toc">
        <li><a href="#complementary-filters"><span class="secno">4.5.1</span> <span class="content">Complementary filter</span></a>
       </ol>
      <li><a href="#gravity-and-linear-acceleration"><span class="secno">4.6</span> <span class="content">Gravity and Linear Acceleration Sensor</span></a>
      <li><a href="#usecases-and-requirements"><span class="secno">4.7</span> <span class="content">Use Cases and Requirements</span></a>
     </ol>
    <li>
     <a href="#index"><span class="secno"></span> <span class="content">Index</span></a>
     <ol class="toc">
      <li><a href="#index-defined-here"><span class="secno"></span> <span class="content">Terms defined by this specification</span></a>
      <li><a href="#index-defined-elsewhere"><span class="secno"></span> <span class="content">Terms defined by reference</span></a>
     </ol>
    <li>
     <a href="#references"><span class="secno"></span> <span class="content">References</span></a>
     <ol class="toc">
      <li><a href="#normative"><span class="secno"></span> <span class="content">Normative References</span></a>
      <li><a href="#informative"><span class="secno"></span> <span class="content">Informative References</span></a>
     </ol>
   </ol>
  </nav>
  <main>
   <p> <em>This section describes the status of this document at the time of its
  publication. Other documents may supersede this document. A list of
  current <abbr title="World Wide Web Consortium">W3C</abbr> publications
  and the latest revision of this technical report can be found in the <a href="https://www.w3.org/TR/"><abbr title="World Wide Web Consortium">W3C</abbr> technical reports index</a> at
  https://www.w3.org/TR/.</em> </p>
   <p> This is work in progress. The final version of this document planned to
  be published as a Working Group Note. </p>
   <p> This document was published by the <a href="https://www.w3.org/2009/dap/">Device and Sensors Working Group</a> as a
  Working Draft. This document is intended to become a W3C Recommendation. </p>
   <p> If you wish to make comments regarding this document, please send them to <a href="mailto:public-device-apis@w3.org?Subject=%5Bmotion-sensors%5D%20PUT%20SUBJECT%20HERE"> public-device-apis@w3.org</a> (<a href="mailto:public-device-apis-request@w3.org?subject=subscribe">subscribe</a>, <a href="https://lists.w3.org/Archives/Public/public-device-apis/">archives</a>).
  When sending e-mail, please put the text “motion-sensors” in the subject,
  preferably like this: “[motion-sensors] <em>…summary of comment…</em>”.
  All comments are welcome. </p>
   <p> Publication as a Working Group Note does not imply endorsement by the <abbr title="World Wide Web Consortium">W3C</abbr> Membership. This is a
  draft document and may be updated, replaced or obsoleted by other
  documents at any time. It is inappropriate to cite this document as other
  than work in progress. </p>
   <p> This document was produced by a group operating under the <a href="https://www.w3.org/Consortium/Patent-Policy-20040205/">5 February 2004 W3C
  Patent Policy</a>. W3C maintains a <a href="https://www.w3.org/2004/01/pp-impl/43696/status" rel="disclosure">public
  list of any patent disclosures</a> made in connection with the deliverables
  of the group; that page also includes instructions for disclosing a patent.
  An individual who has actual knowledge of a patent which the individual
  believes contains <a href="https://www.w3.org/Consortium/Patent-Policy-20040205/#def-essential"> Essential Claim(s)</a> must disclose the information in accordance with <a href="https://www.w3.org/Consortium/Patent-Policy-20040205/#sec-Disclosure"> section 6 of the W3C Patent Policy</a>. </p>
   <p> This document is governed by the <a href="https://www.w3.org/2017/Process-20170301/" id="w3c_process_revision">1 March 2017 <abbr title="World Wide Web Consortium">W3C</abbr> Process Document</a>. </p>
   <h2 class="heading settled" data-level="1" id="intro"><span class="secno">1. </span><span class="content">Introduction</span><a class="self-link" href="#intro"></a></h2>
   <p>There are a handful of different motion sensors available in modern hardware such
as phones.</p>
   <p>The motion sensors extends the Generic Sensor API <a data-link-type="biblio" href="#biblio-generic-sensor">[GENERIC-SENSOR]</a> to expose
a class of low-level and fusion sensors. This document explains the relationship
between these sensors.</p>
   <p>The low-level sensors include:</p>
   <ul>
    <li data-md>
     <p><a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer">Accelerometer</a></p>
    <li data-md>
     <p><a data-link-type="dfn" href="#gyroscope" id="ref-for-gyroscope">Gyroscope</a></p>
    <li data-md>
     <p><a data-link-type="dfn" href="#magnetometer-magnetometers" id="ref-for-magnetometer-magnetometers">Magnetometer</a></p>
   </ul>
   <p>Multiple new sensors can be created using the data from these above sensors
in different ways. These are commonly known as fusion sensors.</p>
   <h2 class="heading settled" data-level="2" id="security-and-privacy"><span class="secno">2. </span><span class="content">Security and Privacy Considerations</span><a class="self-link" href="#security-and-privacy"></a></h2>
   <p>There are no specific security and privacy considerations
beyond those described in the Generic Sensor API <a data-link-type="biblio" href="#biblio-generic-sensor">[GENERIC-SENSOR]</a>.</p>
   <h2 class="heading settled" data-level="3" id="low-level-sensors"><span class="secno">3. </span><span class="content">Low-level Sensors</span><a class="self-link" href="#low-level-sensors"></a></h2>
   <h3 class="heading settled" data-level="3.1" id="accelerometer-sensor"><span class="secno">3.1. </span><span class="content">Accelerometer</span><a class="self-link" href="#accelerometer-sensor"></a></h3>
   <p>A raw <dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="accelerometer">accelerometer</dfn> sensor measures changes in acceleration in 3 different
directions, but is affected by <i><a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity">gravity</a></i>. The <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#accelerometer-interface" id="ref-for-accelerometer-interface">Accelerometer interface</a> is defined in <a data-link-type="biblio" href="#biblio-accelerometer">[ACCELEROMETER]</a> specification.</p>
   <p>The <a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer①">Accelerometer</a> sensor is an <dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="inertial-frame-sensor">inertial-frame sensor</dfn>, this means that when the device
is in free fall, the acceleration is 0 m/s<sup>2</sup> in the falling direction, and
when a device is laying flat on a table, the acceleration in upwards direction will be equal
to the Earth <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity①">gravity</a>, i.e. g ≡ 9.8 m/s<sup>2</sup> as it is measuring the force of the table
pushing the device upwards.</p>
   <p>Accelerometers are less useful by themselves and often take part in other fusion sensors,
but they do have some purposes like registering shakes, steps and the like.</p>
   <p>Often for such use-cases the developer is interested in the <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#linear-acceleration" id="ref-for-linear-acceleration">linear acceleration</a> which is
the acceleration without the <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity②">gravity</a>, called <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity③">gravity</a> compensation
(See <a data-link-type="dfn" href="#linear-acceleration-sensor" id="ref-for-linear-acceleration-sensor">Linear Acceleration Sensor</a>); or the developer is interested in the isolated <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity④">gravity</a>, 
in order to know the <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity⑤">gravity</a> vector (see <a data-link-type="dfn" href="#gravity-sensor" id="ref-for-gravity-sensor">Gravity Sensor</a>), which can be useful for some
kinds of sensor fusion like creating a magnetic compass.</p>
   <p>For acceleration, you usually care about the big changes and want to avoid noise, like the <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity⑥">gravity</a>, thus a <a data-link-type="dfn" href="#high-pass-filter" id="ref-for-high-pass-filter">high-pass filter</a> can help isolate the <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#linear-acceleration" id="ref-for-linear-acceleration①">linear acceleration</a> and a <a data-link-type="dfn" href="#low-pass-filter" id="ref-for-low-pass-filter">low-pass
filter</a> can help isolate the <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity⑦">gravity</a>. A <a data-link-type="dfn" href="#low-pass-filter" id="ref-for-low-pass-filter①">low-pass filter</a> can thus be useful for measuring a
tilt. Unfortunately, any <a data-link-type="dfn" href="#high-pass-filter" id="ref-for-high-pass-filter①">high-pass filter</a> or <a data-link-type="dfn" href="#low-pass-filter" id="ref-for-low-pass-filter②">low-pass filter</a> introduces a delay, which may or may not be
acceptable.</p>
   <p>Notice, as accelerometers report <i>acceleration</i>, you need to integrate to get <i>velocity</i>:</p>
   <p>v = ∫a×∂t</p>
   <p>And again to get <i>position</i>:</p>
   <p>x = ∫v×∂t</p>
   <p>An integral creates drift, and a double integral amplifies that:</p>
   <p>a = g×sin(θ), x = ½×at<sup>2</sup></p>
   <p>So position from an accelerometer is very imprecise and not very useful.</p>
   <h3 class="heading settled" data-level="3.2" id="gyroscope-sensor"><span class="secno">3.2. </span><span class="content">Gyroscope</span><a class="self-link" href="#gyroscope-sensor"></a></h3>
   <p>A <dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="gyroscope">gyroscope</dfn> senses <i><a data-link-type="dfn" href="https://w3c.github.io/gyroscope#angular-velocity" id="ref-for-angular-velocity">angular velocity</a></i>, relative to itself, thus it measures its own rotation,
using an inertial force called the Coriolis effect. Gyroscopes oscillate at relative high frequency in
order to measure this and are thus one of the most power hungry motion sensors. This also means
that they can easily be affected by other vibrations, like a vibration (rumble) motor or speaker
on the same device. The <a data-link-type="dfn" href="https://w3c.github.io/gyroscope#gyroscope-interface" id="ref-for-gyroscope-interface">Gyroscope interface</a> is defined in <a data-link-type="biblio" href="#biblio-gyroscope">[GYROSCOPE]</a> specification.</p>
   <p>In order to get rotation (angle) from a gyroscope, which senses <a data-link-type="dfn" href="https://w3c.github.io/gyroscope#angular-velocity" id="ref-for-angular-velocity①">angular velocity</a>, you need to
perform a single integration.</p>
   <p>f ≡ frequency</p>
   <p>∫cos(2π×ft)) = (1/(2π×f)) × sin(2π×ft)</p>
   <p>But be aware that integration turns noise into drift. As we see above, the integration gets a
1/f outside, meaning that high frequency (f) noise disappears with integration, i.e. a noise
of frequency will drop by a factor of a 100, but a very low frequency will be amplified,
meaning the gyroscope will drift over time.</p>
   <p>So in order to do it well you need to do it quickly and as you see below, we multiply with the
∂t, so any error in the reported time difference will manifest itself like the drift above.</p>
   <p>θ<sub>n</sub> = θ<sub>n-1</sub> + ω × ∂t</p>
   <p>With ω denoting the <a data-link-type="dfn" href="https://w3c.github.io/gyroscope#angular-velocity" id="ref-for-angular-velocity②">angular velocity</a> and θ, the resulting angle.</p>
   <p>Most gyroscope sensors perform <a data-link-type="dfn" href="https://w3c.github.io/sensors#calibration" id="ref-for-calibration">calibration</a> by applying some sort of <i>drift compensation</i> in hardware for known low frequency caused by adjacent hardware on the device.</p>
   <h3 class="heading settled" data-level="3.3" id="magnetometer-sensor"><span class="secno">3.3. </span><span class="content">Magnetometer</span><a class="self-link" href="#magnetometer-sensor"></a></h3>
   <p><dfn class="dfn-paneled" data-dfn-for="magnetometer" data-dfn-type="dfn" data-noexport id="magnetometer-magnetometers">Magnetometers</dfn> are <i><a data-link-type="dfn" href="https://w3c.github.io/magnetometer#magnetic-field" id="ref-for-magnetic-field">magnetic field</a> sensors</i>, which means that without
any strong magnetic influence close by, it will sense the Earth’s <a data-link-type="dfn" href="https://w3c.github.io/magnetometer#magnetic-field" id="ref-for-magnetic-field①">magnetic field</a>, which more or less points
in the direction of North, but not true North. The <a data-link-type="dfn" href="https://w3c.github.io/magnetometer#magnetometer-interface" id="ref-for-magnetometer-interface">Magnetometer interface</a> is defined in <a data-link-type="biblio" href="#biblio-magnetometer">[MAGNETOMETER]</a> specification.</p>
   <p>As said, magnetometers are very sensitive to outside influence, like anything on a table that
has been slightly magnetized, and it is even affected by other things inside a device, though
the device manufacturer can compensate for this somewhat. In practise though, these sensors
work quite well for most common use-cases.</p>
   <p>As long as nothing that is magnetized in the surrounding is moving around, the magnetometer
readings are stable enough to be used to isolate <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity⑧">gravity</a> as mentioned above.</p>
   <p>Magnetometer is a 3-axis sensor, which means it gives a 3D vector pointing to the strongest <a data-link-type="dfn" href="https://w3c.github.io/magnetometer#magnetic-field" id="ref-for-magnetic-field②">magnetic field</a>. It also means that it does not enforce a specific device orientation in order
to work.</p>
   <p>In order to tell how the device is being held, though, you need a <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity⑨">gravity</a> vector, which as a bare
minimum requires an accelerometer in the case of low pass filtering, and additionally a gyroscope
if more precise readings are needed. This is called <dfn data-dfn-type="dfn" data-noexport id="tilt-compensation">tilt compensation<a class="self-link" href="#tilt-compensation"></a></dfn>.</p>
   <p>The most common use-case for magnetometers are as part of sensor fusion, in order to generate an
Orientation Sensor which is stationary to the Earth plane, or a compass, which is basically the
former with corrections to the declination depending on geolocation position, such that it points
to the true North.</p>
   <h2 class="heading settled" data-level="4" id="highlevel-sensors"><span class="secno">4. </span><span class="content">High-level Sensors</span><a class="self-link" href="#highlevel-sensors"></a></h2>
   <p>As mentioned above, each sensor has its own issues, such as noise and drift, and often need some
kind of compensation using input from a different sensor. Put another way, one sensor might not
be very precise on its own, but the sum of multiple sensory input can be much more stable.</p>
   <p>Unfortunately, sensors require power, and the more sensors and the higher the measuring frequency,
higher the power consumption. The gyroscope is typically considered more power hungry than the
rest, as it needs to vibrate at a certain frequency in order to measure the <a data-link-type="dfn" href="https://w3c.github.io/gyroscope#angular-velocity" id="ref-for-angular-velocity③">angular velocity</a>.</p>
   <p>For the above reasons, it is always important to consider the minimum set of sensors which
solves a task satisfactory. As many devices today can do certain kinds of sensor fusion in
hardware, it most often makes sense to use these from a power and performance point of view.</p>
   <h3 class="heading settled" data-level="4.1" id="fusion-sensors"><span class="secno">4.1. </span><span class="content">Common fusion sensors</span><a class="self-link" href="#fusion-sensors"></a></h3>
   <p>Below is a list of fusion sensors and what sensors they usually are made up of:</p>
   <table>
    <thead>
     <tr>
      <th>Sensor type
      <th>Underlying physical sensors
    <tfoot>
     <tr>
      <td><a data-link-type="dfn" href="#relative-orientation-sensor" id="ref-for-relative-orientation-sensor">Relative Orientation Sensor</a>
      <td><a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer②">Accelerometer</a>, <a data-link-type="dfn" href="#gyroscope" id="ref-for-gyroscope①">Gyroscope</a>, MUST NOT USE <a data-link-type="dfn" href="#magnetometer-magnetometers" id="ref-for-magnetometer-magnetometers①">Magnetometer</a>
    <tbody>
     <tr>
      <td><a data-link-type="dfn" href="#absolute-orientation-sensor" id="ref-for-absolute-orientation-sensor">Absolute Orientation Sensor</a>
      <td><a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer③">Accelerometer</a>, <a data-link-type="dfn" href="#magnetometer-magnetometers" id="ref-for-magnetometer-magnetometers②">Magnetometer</a>, AND (when present) <a data-link-type="dfn" href="#gyroscope" id="ref-for-gyroscope②">Gyroscope</a>
    <tbody>
     <tr>
      <td><a data-link-type="dfn" href="#geomagnetic-orientation-sensor" id="ref-for-geomagnetic-orientation-sensor">Geomagnetic Orientation Sensor</a>
      <td><a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer④">Accelerometer</a>, <a data-link-type="dfn" href="#magnetometer-magnetometers" id="ref-for-magnetometer-magnetometers③">Magnetometer</a>, MUST NOT USE <a data-link-type="dfn" href="#gyroscope" id="ref-for-gyroscope③">Gyroscope</a>
    <tbody>
     <tr>
      <td><a data-link-type="dfn" href="#gravity-sensor" id="ref-for-gravity-sensor①">Gravity Sensor</a>
      <td><a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer⑤">Accelerometer</a>, <a data-link-type="dfn" href="#gyroscope" id="ref-for-gyroscope④">Gyroscope</a>
    <tbody>
     <tr>
      <td><a data-link-type="dfn" href="#linear-acceleration-sensor" id="ref-for-linear-acceleration-sensor①">Linear Acceleration Sensor</a>
      <td><a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer⑥">Accelerometer</a>, AND EITHER <a data-link-type="dfn" href="#gyroscope" id="ref-for-gyroscope⑤">Gyroscope</a> OR <a data-link-type="dfn" href="#magnetometer-magnetometers" id="ref-for-magnetometer-magnetometers④">Magnetometer</a>
   </table>
   <h3 class="heading settled" data-level="4.2" id="pass-filters"><span class="secno">4.2. </span><span class="content">Low and high pass filters</span><a class="self-link" href="#pass-filters"></a></h3>
   <p>As mentioned earlier, it is possible to remove noise (high or low frequency) using
low and high pass filters. As the names say, the filters let low or high frequencies
pass and thus cut of, or minimize, the effect of unwanted frequencies.</p>
   <h4 class="heading settled" data-level="4.2.1" id="low-pass-filters"><span class="secno">4.2.1. </span><span class="content">Low-pass filter</span><a class="self-link" href="#low-pass-filters"></a></h4>
   <p>A common way to create a <dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="low-pass-filter">low-pass filter</dfn> is to only use a percentage of
the latest value and take the rest from the existing value. In a way this means that
the filter remembers common values and thus smoothens out uncommon values which most
often are a result of noise. As it uses a big percentage of the existing value, this
solution introduces a delay in registering the actual events.</p>
   <div class="example" id="example-716517d4">
    <a class="self-link" href="#example-716517d4"></a> 
<pre class="highlight"><c- kr>class</c-> LowPassFilterData <c- p>{</c->
  constructor<c- p>(</c->reading<c- p>,</c-> bias<c- p>)</c-> <c- p>{</c->
    Object<c- p>.</c->assign<c- p>(</c-><c- k>this</c-><c- p>,</c-> <c- p>{</c-> x<c- o>:</c-> reading<c- p>.</c->x<c- p>,</c-> y<c- o>:</c-> reading<c- p>.</c->y<c- p>,</c-> z<c- o>:</c-> reading<c- p>.</c->z <c- p>});</c->
    <c- k>this</c-><c- p>.</c->bias <c- o>=</c-> bias<c- p>;</c->
  <c- p>}</c->

  update<c- p>(</c->reading<c- p>)</c-> <c- p>{</c->
    <c- k>this</c-><c- p>.</c->x <c- o>=</c-> <c- k>this</c-><c- p>.</c->x <c- o>*</c-> <c- k>this</c-><c- p>.</c->bias <c- o>+</c-> reading<c- p>.</c->x <c- o>*</c-> <c- p>(</c-><c- mi>1</c-> <c- o>-</c-> <c- k>this</c-><c- p>.</c->bias<c- p>);</c->
    <c- k>this</c-><c- p>.</c->y <c- o>=</c-> <c- k>this</c-><c- p>.</c->y <c- o>*</c-> <c- k>this</c-><c- p>.</c->bias <c- o>+</c-> reading<c- p>.</c->y <c- o>*</c-> <c- p>(</c-><c- mi>1</c-> <c- o>-</c-> <c- k>this</c-><c- p>.</c->bias<c- p>);</c->
    <c- k>this</c-><c- p>.</c->z <c- o>=</c-> <c- k>this</c-><c- p>.</c->z <c- o>*</c-> <c- k>this</c-><c- p>.</c->bias <c- o>+</c-> reading<c- p>.</c->z <c- o>*</c-> <c- p>(</c-><c- mi>1</c-> <c- o>-</c-> <c- k>this</c-><c- p>.</c->bias<c- p>);</c->
  <c- p>}</c->
<c- p>};</c->

<c- kr>const</c-> accl <c- o>=</c-> <c- k>new</c-> Accelerometer<c- p>({</c-> frequency<c- o>:</c-> <c- mi>20</c-> <c- p>});</c->
              
<c- c1>// Isolate gravity with low-pass filter.</c->
<c- kr>const</c-> filter <c- o>=</c-> <c- k>new</c-> LowPassFilterData<c- p>(</c->accl<c- p>,</c-> <c- mf>0.8</c-><c- p>);</c->

accl<c- p>.</c->onchange <c- o>=</c-> <c- p>()</c-> <c- p>=></c-> <c- p>{</c->
  filter<c- p>.</c->update<c- p>(</c->accl<c- p>);</c-> <c- c1>// Pass latest values through filter.</c->
  console<c- p>.</c->log<c- p>(</c-><c- sb>`Isolated gravity (</c-><c- si>${</c->filter<c- p>.</c->x<c- si>}</c-><c- sb>, </c-><c- si>${</c->filter<c- p>.</c->y<c- si>}</c-><c- sb>, </c-><c- si>${</c->filter<c- p>.</c->z<c- si>}</c-><c- sb>)`</c-><c- p>);</c->
<c- p>}</c->

accl<c- p>.</c->start<c- p>();</c->
</pre>
   </div>
   <h4 class="heading settled" data-level="4.2.2" id="high-pass-filters"><span class="secno">4.2.2. </span><span class="content">High-pass filter</span><a class="self-link" href="#high-pass-filters"></a></h4>
   <p><dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="high-pass-filter">High-pass filter</dfn> works like a <a data-link-type="dfn" href="#low-pass-filter" id="ref-for-low-pass-filter③">low-pass filter</a>, but allows only high frequencies to pass through.</p>
   <p>This can be useful to get rid of the drift which builds up over time
with <a data-link-type="dfn" href="#gyroscope" id="ref-for-gyroscope⑥">gyroscope</a> readings.</p>
   <div class="example" id="example-3706d94a">
    <a class="self-link" href="#example-3706d94a"></a> 
<pre class="highlight"><c- kr>class</c-> HighPassFilterData <c- p>{</c->
  constructor<c- p>(</c->reading<c- p>,</c-> cutoffFrequency<c- p>)</c-> <c- p>{</c->
    Object<c- p>.</c->assign<c- p>(</c-><c- k>this</c-><c- p>,</c-> <c- p>{</c-> x<c- o>:</c-> reading<c- p>.</c->x<c- p>,</c-> y<c- o>:</c-> reading<c- p>.</c->y<c- p>,</c-> z<c- o>:</c-> reading<c- p>.</c->z <c- p>});</c->
    <c- k>this</c-><c- p>.</c->cutoff <c- o>=</c-> cutoffFrequency<c- p>;</c->
    <c- k>this</c-><c- p>.</c->timestamp <c- o>=</c-> reading<c- p>.</c->timestamp<c- p>;</c->
  <c- p>}</c->

  update<c- p>(</c->reading<c- p>)</c-> <c- p>{</c->
    <c- a>let</c-> dt <c- o>=</c-> reading<c- p>.</c->timestamp <c- o>-</c-> <c- k>this</c-><c- p>.</c->timestamp <c- o>/</c-> <c- mi>1000</c-><c- p>;</c->
    <c- k>this</c-><c- p>.</c->timestamp <c- o>=</c-> reading<c- p>.</c->timestamp<c- p>;</c->

    <c- k>for</c-> <c- p>(</c-><c- a>let</c-> i <c- k>of</c-> <c- p>[</c-><c- u>"x"</c-><c- p>,</c-> <c- u>"y"</c-><c- p>,</c-> <c- u>"z"</c-><c- p>])</c-> <c- p>{</c->
      <c- a>let</c-> alpha <c- o>=</c-> <c- k>this</c-><c- p>.</c->cutoff <c- o>/</c-> <c- p>(</c-><c- k>this</c-><c- p>.</c->cutoff <c- o>+</c-> dt<c- p>);</c->
      <c- k>this</c-><c- p>[</c->i<c- p>]</c-> <c- o>=</c-> <c- k>this</c-><c- p>[</c->i<c- p>]</c-> <c- o>+</c-> alpha <c- o>*</c-> <c- p>(</c->reading<c- p>[</c->i<c- p>]</c-> <c- o>-</c-> <c- k>this</c-><c- p>[</c->i<c- p>]);</c->
    <c- p>}</c->
  <c- p>}</c->
<c- p>};</c->

<c- kr>const</c-> gyro <c- o>=</c-> <c- k>new</c-> Gyroscope<c- p>({</c-> frequency<c- o>:</c-> <c- mi>20</c-> <c- p>});</c->
              
<c- c1>// Remove drift with a  high pass filter.</c->
<c- kr>const</c-> filter <c- o>=</c-> <c- k>new</c-> HighPassFilterData<c- p>(</c->gyro<c- p>,</c-> <c- mf>0.8</c-><c- p>);</c->

gyro<c- p>.</c->onchange <c- o>=</c-> <c- p>()</c-> <c- p>=></c-> <c- p>{</c->
  filter<c- p>.</c->update<c- p>(</c->gyro<c- p>);</c-> <c- c1>// Pass latest values through filter.</c->
  console<c- p>.</c->log<c- p>(</c-><c- sb>`Steady gyroscope (</c-><c- si>${</c->filter<c- p>.</c->x<c- si>}</c-><c- sb>, </c-><c- si>${</c->filter<c- p>.</c->y<c- si>}</c-><c- sb>, </c-><c- si>${</c->filter<c- p>.</c->z<c- si>}</c-><c- sb>)`</c-><c- p>);</c->
<c- p>}</c->

gyro<c- p>.</c->start<c- p>();</c->
</pre>
   </div>
   <h3 class="heading settled" data-level="4.3" id="absolute-orientation"><span class="secno">4.3. </span><span class="content">Absolute Orientation Sensor</span><a class="self-link" href="#absolute-orientation"></a></h3>
   <p>As mentioned before, the <dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="absolute-orientation-sensor">Absolute Orientation Sensor</dfn>, is one of the common use-cases of a <a data-link-type="dfn" href="#magnetometer-magnetometers" id="ref-for-magnetometer-magnetometers⑤">magnetometer</a>, and is a sensor representing an orientation stationary (fixed to the magnetic
field vector and <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity①⓪">gravity</a> vector) to the Earth plane. The <a data-link-type="dfn" href="https://w3c.github.io/orientation-sensor#absoluteorientationsensor-interface" id="ref-for-absoluteorientationsensor-interface">AbsoluteOrientationSensor interface</a> is defined in <a data-link-type="biblio" href="#biblio-orientation-sensor">[ORIENTATION-SENSOR]</a> specification.</p>
   <p>An absolute orientation sensor can be useful for game controls such as a ball-in-a-maze puzzle, or
for a head-mounted display where you want to be able to rotate the display and look in all
directions.</p>
   <p>As the reference frame of an absolute orientation sensor is stationary, it is not useful as a
controller for say a driving game on a phone, as it would not allow you to move around,
even slightly or slowly, without affecting your driving direction.
(See <a data-link-type="dfn" href="#relative-orientation-sensor" id="ref-for-relative-orientation-sensor①">Relative Orientation Sensor</a>).</p>
   <p>The orientation vector of the <a data-link-type="dfn" href="#absolute-orientation-sensor" id="ref-for-absolute-orientation-sensor①">Absolute Orientation Sensor</a>, can be calculated in the following way:</p>
   <p>As the <a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer⑦">Accelerometer</a> is an <a data-link-type="dfn" href="#inertial-frame-sensor" id="ref-for-inertial-frame-sensor">inertial-frame sensor</a>, the <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity①①">gravity</a> vector will point
towards the sky when the device is mostly stationary, and as long as the device is not in free fall,
there is enough vector length to project the <a data-link-type="dfn" href="https://w3c.github.io/magnetometer#magnetic-field" id="ref-for-magnetic-field③">magnetic field</a> vector onto the ground plane.</p>
   <p class="note" role="note"><span>Note,</span> this will fail at the magnetic poles as the <a data-link-type="dfn" href="https://w3c.github.io/magnetometer#magnetic-field" id="ref-for-magnetic-field④">magnetic field</a> vector will point mostly in
the opposite direction as the <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity①②">gravity</a> vector and generally be very unreliable.</p>
   <p>By taking the cross product between the the <a data-link-type="dfn" href="https://w3c.github.io/magnetometer#magnetic-field" id="ref-for-magnetic-field⑤">magnetic field</a> vector and <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity①③">gravity</a> vector
(see <a data-link-type="dfn" href="#gravity-sensor" id="ref-for-gravity-sensor②">Gravity Sensor</a>), we get a vector which points East on the ground plane, using the right hand rule.</p>
   <p>Now if we take the cross product between the <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity①④">gravity</a> vector and the newly found East vector, the resulting
vector will point in the northern direction towards the Earth’s <a data-link-type="dfn" href="https://w3c.github.io/magnetometer#magnetic-field" id="ref-for-magnetic-field⑥">magnetic field</a>.</p>
   <p>The illustration below represents the case where the device is at rest and y-axis points towards the
North. The reading from the <a data-link-type="dfn" href="#magnetometer-magnetometers" id="ref-for-magnetometer-magnetometers⑥">Magnetometer</a> is {x: 0, y: 11, z: -16} and <a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer⑧">Accelerometer</a> reports
{x: 0.11, y: 0.07, z: 9.81} <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#acceleration" id="ref-for-acceleration">acceleration</a>. The uG is a unit vector representing the <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity①⑤">gravity</a>,
uB represents <a data-link-type="dfn" href="https://w3c.github.io/magnetometer#magnetic-field" id="ref-for-magnetic-field⑦">magnetic field</a> vector, uE = uB × uG and points East. The uN = uG × uE points to
the northern direction.</p>
   <p><img alt="OrientationSensor fusion." src="images/orientation_fusion.png" srcset="images/orientation_fusion.svg" style="display: block;margin: auto;"></p>
   <p>That means an <a data-link-type="dfn" href="#absolute-orientation-sensor" id="ref-for-absolute-orientation-sensor②">Absolute Orientation Sensor</a> is a fusion sensor of the <a data-link-type="dfn" href="#magnetometer-magnetometers" id="ref-for-magnetometer-magnetometers⑦">Magnetometer</a> and the <a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer⑨">Accelerometer</a>, and potentially the <a data-link-type="dfn" href="#gyroscope" id="ref-for-gyroscope⑦">Gyroscope</a> for better isolated <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity①⑥">gravity</a> (see <a data-link-type="dfn" href="#gravity-sensor" id="ref-for-gravity-sensor③">Gravity Sensor</a>).</p>
   <h3 class="heading settled" data-level="4.4" id="geomagnetic-orientation"><span class="secno">4.4. </span><span class="content">Geomagnetic Orientation Sensor</span><a class="self-link" href="#geomagnetic-orientation"></a></h3>
   <p>A <dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="geomagnetic-orientation-sensor">Geomagnetic Orientation Sensor</dfn>, is like a <a data-link-type="dfn" href="#absolute-orientation-sensor" id="ref-for-absolute-orientation-sensor③">Absolute Orientation Sensor</a>, but
doesn’t use the <a data-link-type="dfn" href="#gyroscope" id="ref-for-gyroscope⑧">Gyroscope</a> which means it uses less power. This also means that it
is more sensitive to shakes and movement.</p>
   <p>As the main use-case for a <a data-link-type="dfn" href="#geomagnetic-orientation-sensor" id="ref-for-geomagnetic-orientation-sensor①">Geomagnetic Orientation Sensor</a> is to create a compass, or use
compass direction within a mapping application, this is not much of a problem since people
usually hold the device steady for these use-cases.</p>
   <p>The actual <i>heading</i> (N, S, E, W) can be found by adjusting the rotation vector with
the local <i>declination compensation</i> calculated from the current geolocation position.</p>
   <p>As the sensor uses the <a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer①⓪">accelerometer</a> to get a more steady heading, like when walking,
the rotation vector is projected to the plane perpendicular to the <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity①⑦">gravity</a> vector (as isolated
from the <a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer①①">accelerometer</a>) which more or less represents the ground plane. This also means that
if you are interested in the actual orientation of the <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity①⑧">gravity</a> vector, then use the <a data-link-type="dfn" href="#magnetometer-magnetometers" id="ref-for-magnetometer-magnetometers⑧">magnetometer</a> directly instead.</p>
   <h3 class="heading settled" data-level="4.5" id="relative-orientation"><span class="secno">4.5. </span><span class="content">Relative Orientation Sensor</span><a class="self-link" href="#relative-orientation"></a></h3>
   <p>On most sensor hubs, <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity①⑨">gravity</a> is isolated from the <a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer①②">accelerometer</a> using the <a data-link-type="dfn" href="#gyroscope" id="ref-for-gyroscope⑨">gyroscope</a>,
and the <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#linear-acceleration" id="ref-for-linear-acceleration②">linear acceleration</a> is isolated by removing the isolated <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity②⓪">gravity</a>, from the <a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer①③">accelerometer</a> values.</p>
   <p>This avoids the delay which low and high pass filters introduce.</p>
   <p>One way of doing this is using a Kalman filter or <a data-link-type="dfn" href="#complementary-filter" id="ref-for-complementary-filter">complementary filter</a>, which leads us to
the <dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="relative-orientation-sensor">Relative Orientation Sensor</dfn>. As a <a data-link-type="dfn" href="#complementary-filter" id="ref-for-complementary-filter①">complementary filter</a> yields quite good
results and is easy to implement in hardware, this is a common solution.</p>
   <h4 class="heading settled" data-level="4.5.1" id="complementary-filters"><span class="secno">4.5.1. </span><span class="content">Complementary filter</span><a class="self-link" href="#complementary-filters"></a></h4>
   <p>A <dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="complementary-filter">complementary filter</dfn> can be thought of as a <a data-link-type="dfn" href="#low-pass-filter" id="ref-for-low-pass-filter④">low-pass filter</a> and <a data-link-type="dfn" href="#high-pass-filter" id="ref-for-high-pass-filter②">high-pass filter</a> in one,
complementing the <a data-link-type="dfn" href="#gyroscope" id="ref-for-gyroscope①⓪">gyroscope</a> values with the <a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer①④">accelerometer</a> values:</p>
   <p>θ<sub>n</sub> = α × (θ<sub>n-1</sub> + ω × ∂t) + (1.0 - α) × a</p>
   <p>With α being the weight constant, a the acceleration from <a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer①⑤">accelerometer</a>, ω the <a data-link-type="dfn" href="https://w3c.github.io/gyroscope#angular-velocity" id="ref-for-angular-velocity④">angular
velocity</a> from <a data-link-type="dfn" href="#gyroscope" id="ref-for-gyroscope①①">gyroscope</a> and ∂t being the time between measurements.</p>
   <p>A common value for α is 0.98, which means that 98% of the weight lays on the <a data-link-type="dfn" href="#gyroscope" id="ref-for-gyroscope①②">gyroscope</a> measurements.</p>
   <div class="example" id="example-828cabd4">
    <a class="self-link" href="#example-828cabd4"></a> Manually calculate the relative orientation in Euler angles (radian) using a <a data-link-type="dfn" href="#complementary-filter" id="ref-for-complementary-filter②">complementary filter</a>. 
    <p>The <a data-link-type="dfn" href="#gyroscope" id="ref-for-gyroscope①③">gyroscope</a> measures <i><a data-link-type="dfn" href="https://w3c.github.io/gyroscope#angular-velocity" id="ref-for-angular-velocity⑤">angular velocity</a></i>, so by multiplying with the time difference,
  we get the <i>change of angle</i>. This change is always calculated relative to the current device
  position, so we need to use the <a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer①⑥">accelerometer</a>, which includes <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity②①">gravity</a>, to calibrate this
  to the ground plane.</p>
    <p>The values from the <a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer①⑦">accelerometer</a> bring no information about the heading (alpha, the
  rotation around z), so we don’t include that in our alpha component. On the other hand,
  the <a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer①⑧">accelerometer</a> (due to <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity②②">gravity</a>) provides information on how the device is held around
  the x and y axis (beta and gamma).</p>
    <p>When there is no or little movement, the vector obtained from the <a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer①⑨">accelerometer</a> reading will contribute more to the (alpha, beta, gamma) angles than the <a data-link-type="dfn" href="#gyroscope" id="ref-for-gyroscope①④">gyroscope</a>.</p>
    <p>As values from a steady <a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer②⓪">accelerometer</a> represent the <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity②③">gravity</a> vector, and we don’t
  include the z component in the alpha, the result of this is that the orientation will
  just follow the <a data-link-type="dfn" href="#gyroscope" id="ref-for-gyroscope①⑤">gyroscope</a> and be stable. But as the origin of the heading depends on 
  the device position at start this a <i>device-relative orientation sensor</i>.</p>
<pre class="highlight"><c- kr>const</c-> options <c- o>=</c-> <c- p>{</c-> frequency<c- o>:</c-> <c- mi>50</c-> <c- p>};</c->

<c- kr>const</c-> accl <c- o>=</c-> <c- k>new</c-> Accelerometer<c- p>(</c->options<c- p>);</c->
<c- kr>const</c-> gyro <c- o>=</c-> <c- k>new</c-> Gyroscope<c- p>(</c->options<c- p>);</c->

<c- a>let</c-> timestamp <c- o>=</c-> <c- kc>null</c-><c- p>;</c->
<c- a>let</c-> alpha <c- o>=</c-> beta <c- o>=</c-> gamma <c- o>=</c-> <c- mi>0</c-><c- p>;</c->
<c- kr>const</c-> bias <c- o>=</c-> <c- mf>0.98</c-><c- p>;</c->

gyro<c- p>.</c->onchange <c- o>=</c-> <c- p>()</c-> <c- p>=></c-> <c- p>{</c->
   <c- a>let</c-> dt <c- o>=</c-> timestamp <c- o>?</c-> <c- p>(</c->gyro<c- p>.</c->timestamp <c- o>-</c-> timestamp<c- p>)</c-> <c- o>/</c-> <c- mi>1000</c-> <c- o>:</c-> <c- mi>0</c-><c- p>;</c->
   timestamp <c- o>=</c-> gyro<c- p>.</c->timestamp<c- p>;</c->

   <c- c1>// Treat the acceleration vector as an orientation vector by normalizing it.</c->
   <c- c1>// Keep in mind that the if the device is flipped, the vector will just be</c->
   <c- c1>// pointing in the other direction, so we have no way to know from the</c->
   <c- c1>// accelerometer data which way the device is oriented.</c->
   <c- kr>const</c-> norm <c- o>=</c-> Math<c- p>.</c->sqrt<c- p>(</c->accl<c- p>.</c->x <c- o>**</c-> <c- mi>2</c-> <c- o>+</c-> accl<c- p>.</c->y <c- o>**</c-> <c- mi>2</c-> <c- o>+</c-> accl<c- p>.</c->z <c- o>**</c-> <c- mi>2</c-><c- p>);</c->

   <c- c1>// As we only can cover half (PI rad) of the full spectrum (2*PI rad) we multiply</c->
   <c- c1>// the unit vector with values from [-1, 1] with PI/2, covering [-PI/2, PI/2].</c->
   <c- kr>const</c-> scale <c- o>=</c-> Math<c- p>.</c->PI <c- o>/</c-> <c- mi>2</c-><c- p>;</c->

   alpha <c- o>=</c-> alpha <c- o>+</c-> gyro<c- p>.</c->z <c- o>*</c-> dt<c- p>;</c->
   beta <c- o>=</c-> bias <c- o>*</c-> <c- p>(</c->beta <c- o>+</c-> gyro<c- p>.</c->x <c- o>*</c-> dt<c- p>)</c-> <c- o>+</c-> <c- p>(</c-><c- mf>1.0</c-> <c- o>-</c-> bias<c- p>)</c-> <c- o>*</c-> <c- p>(</c->accl<c- p>.</c->x <c- o>*</c-> scale <c- o>/</c-> norm<c- p>);</c->
   gamma <c- o>=</c-> bias <c- o>*</c-> <c- p>(</c->gamma <c- o>+</c-> gyro<c- p>.</c->y <c- o>*</c-> dt<c- p>)</c-> <c- o>+</c-> <c- p>(</c-><c- mf>1.0</c-> <c- o>-</c-> bias<c- p>)</c-> <c- o>*</c-> <c- p>(</c->accl<c- p>.</c->y <c- o>*</c-> <c- o>-</c->scale <c- o>/</c-> norm<c- p>);</c->

   <c- c1>// Do something with Euler angles (alpha, beta, gamma).</c->
 <c- p>};</c->

 accl<c- p>.</c->start<c- p>();</c->
 gyro<c- p>.</c->start<c- p>();</c->
</pre>
   </div>
   <div class="example" id="example-c2e7c2b3">
    <a class="self-link" href="#example-c2e7c2b3"></a> An device-adjusting, relative orientation sensor. 
    <p>From the above example, we notice that the alpha represented the initial heading
  orientation. We also know that this heading might drift over time due to being
  based on the <a data-link-type="dfn" href="#gyroscope" id="ref-for-gyroscope①⑥">gyroscope</a>.</p>
    <p>In some situations you might want the orientation to drift towards your current
  position. This can be useful for a controller inside a virtual reality
  environment, where you want a car to follow the heading of your controller, but you
  might move and turn around while playing. That would more or less work like driving
  a real car.</p>
    <p>Changing one line in the above accomplishes that.</p>
<pre class="highlight"><c- kr>const</c-> zeroBias <c- o>=</c-> <c- mf>0.02</c-><c- p>;</c->
alpha <c- o>=</c-> <c- p>(</c-><c- mi>1</c-> <c- o>-</c-> zeroBias<c- p>)</c-> <c- o>*</c-> <c- p>(</c->alpha <c- o>+</c-> gyro<c- p>.</c->z <c- o>*</c-> dt<c- p>);</c->
</pre>
    <p>With the above 2% of the alpha consists of the value 0. Thus, when the device is being
  held more or less steady, the heading will move towards 0, meaning being adjusted to
  your current device position and not positioned according to the surroundings.</p>
    <p>This example shows how useful manual fusion can be at times.</p>
   </div>
   <h3 class="heading settled" data-level="4.6" id="gravity-and-linear-acceleration"><span class="secno">4.6. </span><span class="content">Gravity and Linear Acceleration Sensor</span><a class="self-link" href="#gravity-and-linear-acceleration"></a></h3>
   <p>The <a data-link-type="dfn" href="#complementary-filter" id="ref-for-complementary-filter③">complementary filter</a> used above is quite good at isolating the <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity②④">gravity</a>, and most sensor
hubs thus isolate <i><a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity②⑤">gravity</a></i> from the <a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer②①">accelerometer</a> using the <a data-link-type="dfn" href="#gyroscope" id="ref-for-gyroscope①⑦">gyroscope</a>, and the <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#linear-acceleration" id="ref-for-linear-acceleration③">linear acceleration</a> is isolated by removing the isolated <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity②⑥">gravity</a>, from the <a data-link-type="dfn" href="#accelerometer" id="ref-for-accelerometer②②">accelerometer</a> values.</p>
   <p>This also means that the <dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="linear-acceleration-sensor">Linear Acceleration Sensor</dfn> and the <dfn class="dfn-paneled" data-dfn-type="dfn" data-noexport id="gravity-sensor">Gravity Sensor</dfn> as exposed by most sensor hubs are most likely fusion sensors.</p>
   <p><a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity②⑦">Gravity</a> can also be removed from a <a data-link-type="dfn" href="#linear-acceleration-sensor" id="ref-for-linear-acceleration-sensor②">linear acceleration sensor</a> using a <a data-link-type="dfn" href="#magnetometer-magnetometers" id="ref-for-magnetometer-magnetometers⑨">magnetometer</a>,
as the <a data-link-type="dfn" href="https://w3c.github.io/magnetometer#magnetic-field" id="ref-for-magnetic-field⑧">magnetic field</a> vector is more or less stable.</p>
   <p>The <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#linearaccelerationsensor-interface" id="ref-for-linearaccelerationsensor-interface">LinearAccelerationSensor interface</a> and <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravitysensor-interface" id="ref-for-gravitysensor-interface">GravitySensor interface</a> are defined in <a data-link-type="biblio" href="#biblio-accelerometer">[ACCELEROMETER]</a> specification.</p>
   <p class="note" role="note"><span>Note,</span> as the <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#gravity" id="ref-for-gravity②⑧">gravity</a> changes with the frequency of the movements, i.e., 0 in falling direction
in free fall, you can imagine that <a data-link-type="dfn" href="https://w3c.github.io/accelerometer#linear-acceleration" id="ref-for-linear-acceleration④">linear acceleration</a> will be quite imprecise if you are
trying to detect a shake, so keep that in mind.</p>
   <h3 class="heading settled" data-level="4.7" id="usecases-and-requirements"><span class="secno">4.7. </span><span class="content">Use Cases and Requirements</span><a class="self-link" href="#usecases-and-requirements"></a></h3>
   <p>Advanced motion sensor use-cases could have requirements for accurate sensor readings, high
sampling rates at which hardware sensor operates, and reading delivery rate that is preferable
for particular application.</p>
   <p>Motion sensors can be used for variety of advanced use-cases, such as:</p>
   <ul>
    <li data-md>
     <p>Virtual reality HMD tracking <a data-link-type="biblio" href="#biblio-hmdtracking">[HMDTRACKING]</a></p>
    <li data-md>
     <p>Sensor assisted indoor navigation <a data-link-type="biblio" href="#biblio-indoornav">[INDOORNAV]</a>, <a data-link-type="biblio" href="#biblio-ipin">[IPIN]</a></p>
    <li data-md>
     <p>Photo and video capture stabilization <a data-link-type="biblio" href="#biblio-rollstabilizer">[ROLLSTABILIZER]</a>, <a data-link-type="biblio" href="#biblio-videostabilizer">[VIDEOSTABILIZER]</a></p>
    <li data-md>
     <p>Games that require high-frequency sampling rates with high accuracy readings.</p>
   </ul>
   <p>The generic requirement for games or UI applications that use motion sensors is to have a new
sensor reading per rendered frame. The higher sampling rates in this case, will reduce latency,
thus improve user experience.</p>
   <p>In case of virtual reality HMD tracking, sensors might run at very high sampling rates
(up to several kHz) and minimize motion-to-photon latency by providing latest sensor reading
for every rendered frame at refresh rates of 75-120Hz.</p>
   <p>Indoor navigation or non-realtime video (image) stabilization applications could benefit from
collecting high accuracy sensor readings at high sampling rates (80-100Hz), so that data
processing algorithms have enough samples to provide accurate results.</p>
  </main>
<script src="https://www.w3.org/scripts/TR/2016/fixup.js"></script>
  <h2 class="no-num no-ref heading settled" id="index"><span class="content">Index</span><a class="self-link" href="#index"></a></h2>
  <h3 class="no-num no-ref heading settled" id="index-defined-here"><span class="content">Terms defined by this specification</span><a class="self-link" href="#index-defined-here"></a></h3>
  <ul class="index">
   <li><a href="#absolute-orientation-sensor">Absolute Orientation Sensor</a><span>, in §4.3</span>
   <li><a href="#accelerometer">accelerometer</a><span>, in §3.1</span>
   <li><a href="#complementary-filter">complementary filter</a><span>, in §4.5.1</span>
   <li><a href="#geomagnetic-orientation-sensor">Geomagnetic Orientation Sensor</a><span>, in §4.4</span>
   <li><a href="#gravity-sensor">Gravity Sensor</a><span>, in §4.6</span>
   <li><a href="#gyroscope">gyroscope</a><span>, in §3.2</span>
   <li><a href="#high-pass-filter">High-pass filter</a><span>, in §4.2.2</span>
   <li><a href="#inertial-frame-sensor">inertial-frame sensor</a><span>, in §3.1</span>
   <li><a href="#linear-acceleration-sensor">Linear Acceleration Sensor</a><span>, in §4.6</span>
   <li><a href="#low-pass-filter">low-pass filter</a><span>, in §4.2.1</span>
   <li><a href="#magnetometer-magnetometers">Magnetometers</a><span>, in §3.3</span>
   <li><a href="#relative-orientation-sensor">Relative Orientation Sensor</a><span>, in §4.5</span>
   <li><a href="#tilt-compensation">tilt compensation</a><span>, in §3.3</span>
  </ul>
  <aside class="dfn-panel" data-for="term-for-acceleration">
   <a href="https://w3c.github.io/accelerometer#acceleration">https://w3c.github.io/accelerometer#acceleration</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-acceleration">4.3. Absolute Orientation Sensor</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-accelerometer-interface">
   <a href="https://w3c.github.io/accelerometer#accelerometer-interface">https://w3c.github.io/accelerometer#accelerometer-interface</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-accelerometer-interface">3.1. Accelerometer</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-gravity">
   <a href="https://w3c.github.io/accelerometer#gravity">https://w3c.github.io/accelerometer#gravity</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-gravity">3.1. Accelerometer</a> <a href="#ref-for-gravity①">(2)</a> <a href="#ref-for-gravity②">(3)</a> <a href="#ref-for-gravity③">(4)</a> <a href="#ref-for-gravity④">(5)</a> <a href="#ref-for-gravity⑤">(6)</a> <a href="#ref-for-gravity⑥">(7)</a> <a href="#ref-for-gravity⑦">(8)</a>
    <li><a href="#ref-for-gravity⑧">3.3. Magnetometer</a> <a href="#ref-for-gravity⑨">(2)</a>
    <li><a href="#ref-for-gravity①⓪">4.3. Absolute Orientation Sensor</a> <a href="#ref-for-gravity①①">(2)</a> <a href="#ref-for-gravity①②">(3)</a> <a href="#ref-for-gravity①③">(4)</a> <a href="#ref-for-gravity①④">(5)</a> <a href="#ref-for-gravity①⑤">(6)</a> <a href="#ref-for-gravity①⑥">(7)</a>
    <li><a href="#ref-for-gravity①⑦">4.4. Geomagnetic Orientation Sensor</a> <a href="#ref-for-gravity①⑧">(2)</a>
    <li><a href="#ref-for-gravity①⑨">4.5. Relative Orientation Sensor</a> <a href="#ref-for-gravity②⓪">(2)</a>
    <li><a href="#ref-for-gravity②①">4.5.1. Complementary filter</a> <a href="#ref-for-gravity②②">(2)</a> <a href="#ref-for-gravity②③">(3)</a>
    <li><a href="#ref-for-gravity②④">4.6. Gravity and Linear Acceleration Sensor</a> <a href="#ref-for-gravity②⑤">(2)</a> <a href="#ref-for-gravity②⑥">(3)</a> <a href="#ref-for-gravity②⑦">(4)</a> <a href="#ref-for-gravity②⑧">(5)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-gravitysensor-interface">
   <a href="https://w3c.github.io/accelerometer#gravitysensor-interface">https://w3c.github.io/accelerometer#gravitysensor-interface</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-gravitysensor-interface">4.6. Gravity and Linear Acceleration Sensor</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-linear-acceleration">
   <a href="https://w3c.github.io/accelerometer#linear-acceleration">https://w3c.github.io/accelerometer#linear-acceleration</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-linear-acceleration">3.1. Accelerometer</a> <a href="#ref-for-linear-acceleration①">(2)</a>
    <li><a href="#ref-for-linear-acceleration②">4.5. Relative Orientation Sensor</a>
    <li><a href="#ref-for-linear-acceleration③">4.6. Gravity and Linear Acceleration Sensor</a> <a href="#ref-for-linear-acceleration④">(2)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-linearaccelerationsensor-interface">
   <a href="https://w3c.github.io/accelerometer#linearaccelerationsensor-interface">https://w3c.github.io/accelerometer#linearaccelerationsensor-interface</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-linearaccelerationsensor-interface">4.6. Gravity and Linear Acceleration Sensor</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-calibration">
   <a href="https://w3c.github.io/sensors#calibration">https://w3c.github.io/sensors#calibration</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-calibration">3.2. Gyroscope</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-angular-velocity">
   <a href="https://w3c.github.io/gyroscope#angular-velocity">https://w3c.github.io/gyroscope#angular-velocity</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-angular-velocity">3.2. Gyroscope</a> <a href="#ref-for-angular-velocity①">(2)</a> <a href="#ref-for-angular-velocity②">(3)</a>
    <li><a href="#ref-for-angular-velocity③">4. High-level Sensors</a>
    <li><a href="#ref-for-angular-velocity④">4.5.1. Complementary filter</a> <a href="#ref-for-angular-velocity⑤">(2)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-gyroscope-interface">
   <a href="https://w3c.github.io/gyroscope#gyroscope-interface">https://w3c.github.io/gyroscope#gyroscope-interface</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-gyroscope-interface">3.2. Gyroscope</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-magnetic-field">
   <a href="https://w3c.github.io/magnetometer#magnetic-field">https://w3c.github.io/magnetometer#magnetic-field</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-magnetic-field">3.3. Magnetometer</a> <a href="#ref-for-magnetic-field①">(2)</a> <a href="#ref-for-magnetic-field②">(3)</a>
    <li><a href="#ref-for-magnetic-field③">4.3. Absolute Orientation Sensor</a> <a href="#ref-for-magnetic-field④">(2)</a> <a href="#ref-for-magnetic-field⑤">(3)</a> <a href="#ref-for-magnetic-field⑥">(4)</a> <a href="#ref-for-magnetic-field⑦">(5)</a>
    <li><a href="#ref-for-magnetic-field⑧">4.6. Gravity and Linear Acceleration Sensor</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-magnetometer-interface">
   <a href="https://w3c.github.io/magnetometer#magnetometer-interface">https://w3c.github.io/magnetometer#magnetometer-interface</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-magnetometer-interface">3.3. Magnetometer</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="term-for-absoluteorientationsensor-interface">
   <a href="https://w3c.github.io/orientation-sensor#absoluteorientationsensor-interface">https://w3c.github.io/orientation-sensor#absoluteorientationsensor-interface</a><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-absoluteorientationsensor-interface">4.3. Absolute Orientation Sensor</a>
   </ul>
  </aside>
  <h3 class="no-num no-ref heading settled" id="index-defined-elsewhere"><span class="content">Terms defined by reference</span><a class="self-link" href="#index-defined-elsewhere"></a></h3>
  <ul class="index">
   <li>
    <a data-link-type="biblio">[ACCELEROMETER]</a> defines the following terms:
    <ul>
     <li><span class="dfn-paneled" id="term-for-acceleration" style="color:initial">acceleration</span>
     <li><span class="dfn-paneled" id="term-for-accelerometer-interface" style="color:initial">accelerometer interface</span>
     <li><span class="dfn-paneled" id="term-for-gravity" style="color:initial">gravity</span>
     <li><span class="dfn-paneled" id="term-for-gravitysensor-interface" style="color:initial">gravitysensor interface</span>
     <li><span class="dfn-paneled" id="term-for-linear-acceleration" style="color:initial">linear acceleration</span>
     <li><span class="dfn-paneled" id="term-for-linearaccelerationsensor-interface" style="color:initial">linearaccelerationsensor interface</span>
    </ul>
   <li>
    <a data-link-type="biblio">[GENERIC-SENSOR]</a> defines the following terms:
    <ul>
     <li><span class="dfn-paneled" id="term-for-calibration" style="color:initial">calibration</span>
    </ul>
   <li>
    <a data-link-type="biblio">[GYROSCOPE]</a> defines the following terms:
    <ul>
     <li><span class="dfn-paneled" id="term-for-angular-velocity" style="color:initial">angular velocity</span>
     <li><span class="dfn-paneled" id="term-for-gyroscope-interface" style="color:initial">gyroscope interface</span>
    </ul>
   <li>
    <a data-link-type="biblio">[MAGNETOMETER]</a> defines the following terms:
    <ul>
     <li><span class="dfn-paneled" id="term-for-magnetic-field" style="color:initial">magnetic field</span>
     <li><span class="dfn-paneled" id="term-for-magnetometer-interface" style="color:initial">magnetometer interface</span>
    </ul>
   <li>
    <a data-link-type="biblio">[ORIENTATION-SENSOR]</a> defines the following terms:
    <ul>
     <li><span class="dfn-paneled" id="term-for-absoluteorientationsensor-interface" style="color:initial">absoluteorientationsensor interface</span>
    </ul>
  </ul>
  <h2 class="no-num no-ref heading settled" id="references"><span class="content">References</span><a class="self-link" href="#references"></a></h2>
  <h3 class="no-num no-ref heading settled" id="normative"><span class="content">Normative References</span><a class="self-link" href="#normative"></a></h3>
  <dl>
   <dt id="biblio-accelerometer">[ACCELEROMETER]
   <dd>Anssi Kostiainen. <a href="https://www.w3.org/TR/accelerometer/">Accelerometer</a>. 7 March 2019. WD. URL: <a href="https://www.w3.org/TR/accelerometer/">https://www.w3.org/TR/accelerometer/</a>
   <dt id="biblio-generic-sensor">[GENERIC-SENSOR]
   <dd>Mikhail Pozdnyakov; Alexander Shalamov; Tobie Langel. <a href="https://www.w3.org/TR/generic-sensor/">Generic Sensor API</a>. 7 March 2019. WD. URL: <a href="https://www.w3.org/TR/generic-sensor/">https://www.w3.org/TR/generic-sensor/</a>
   <dt id="biblio-gyroscope">[GYROSCOPE]
   <dd>Anssi Kostiainen. <a href="https://www.w3.org/TR/gyroscope/">Gyroscope</a>. 7 March 2019. WD. URL: <a href="https://www.w3.org/TR/gyroscope/">https://www.w3.org/TR/gyroscope/</a>
   <dt id="biblio-magnetometer">[MAGNETOMETER]
   <dd>Anssi Kostiainen; Rijubrata Bhaumik. <a href="https://www.w3.org/TR/magnetometer/">Magnetometer</a>. 7 March 2019. WD. URL: <a href="https://www.w3.org/TR/magnetometer/">https://www.w3.org/TR/magnetometer/</a>
   <dt id="biblio-orientation-sensor">[ORIENTATION-SENSOR]
   <dd>Mikhail Pozdnyakov; Alexander Shalamov; Kenneth Rohde Christiansen; Anssi Kostiainen. <a href="https://www.w3.org/TR/orientation-sensor/">Orientation Sensor</a>. URL: <a href="https://www.w3.org/TR/orientation-sensor/">https://www.w3.org/TR/orientation-sensor/</a>
  </dl>
  <h3 class="no-num no-ref heading settled" id="informative"><span class="content">Informative References</span><a class="self-link" href="#informative"></a></h3>
  <dl>
   <dt id="biblio-hmdtracking">[HMDTRACKING]
   <dd>LaValle, Steven M., et al.. <a href="http://msl.cs.illinois.edu/~lavalle/papers/LavYerKatAnt14.pdf">Head tracking for the Oculus Rift</a>. 2014. Informational. URL: <a href="http://msl.cs.illinois.edu/~lavalle/papers/LavYerKatAnt14.pdf">http://msl.cs.illinois.edu/~lavalle/papers/LavYerKatAnt14.pdf</a>
   <dt id="biblio-indoornav">[INDOORNAV]
   <dd>Shala, Ubejd, and Angel Rodriguez. <a href="http://www.diva-portal.org/smash/record.jsf?pid=diva2%3A475619&amp;dswid=9050">Indoor positioning using sensor-fusion in android devices</a>. 2011. Informational. URL: <a href="http://www.diva-portal.org/smash/record.jsf?pid=diva2%3A475619&amp;dswid=9050">http://www.diva-portal.org/smash/record.jsf?pid=diva2%3A475619&amp;dswid=9050</a>
   <dt id="biblio-ipin">[IPIN]
   <dd>Gallagher, Thomas, et al.. <a href="http://ieeexplore.ieee.org/abstract/document/6418882/">Indoor positioning system based on sensor fusion for the blind and visually impaired</a>. 2012. Informational. URL: <a href="http://ieeexplore.ieee.org/abstract/document/6418882/">http://ieeexplore.ieee.org/abstract/document/6418882/</a>
   <dt id="biblio-rollstabilizer">[ROLLSTABILIZER]
   <dd>Karpenko, Alexandre, et al.. <a href="http://movement.stanford.edu/papers/stabilization/karpenko_gyro.pdf">Digital video stabilization and rolling shutter correction using gyroscopes</a>. 2011. Informational. URL: <a href="http://movement.stanford.edu/papers/stabilization/karpenko_gyro.pdf">http://movement.stanford.edu/papers/stabilization/karpenko_gyro.pdf</a>
   <dt id="biblio-videostabilizer">[VIDEOSTABILIZER]
   <dd>Hanning, Gustav, et al.. <a href="http://ieeexplore.ieee.org/abstract/document/6130215/">Stabilizing cell phone video using inertial measurement sensors</a>. 2011. Informational. URL: <a href="http://ieeexplore.ieee.org/abstract/document/6130215/">http://ieeexplore.ieee.org/abstract/document/6130215/</a>
  </dl>
  <aside class="dfn-panel" data-for="accelerometer">
   <b><a href="#accelerometer">#accelerometer</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-accelerometer">1. Introduction</a>
    <li><a href="#ref-for-accelerometer①">3.1. Accelerometer</a>
    <li><a href="#ref-for-accelerometer②">4.1. Common fusion sensors</a> <a href="#ref-for-accelerometer③">(2)</a> <a href="#ref-for-accelerometer④">(3)</a> <a href="#ref-for-accelerometer⑤">(4)</a> <a href="#ref-for-accelerometer⑥">(5)</a>
    <li><a href="#ref-for-accelerometer⑦">4.3. Absolute Orientation Sensor</a> <a href="#ref-for-accelerometer⑧">(2)</a> <a href="#ref-for-accelerometer⑨">(3)</a>
    <li><a href="#ref-for-accelerometer①⓪">4.4. Geomagnetic Orientation Sensor</a> <a href="#ref-for-accelerometer①①">(2)</a>
    <li><a href="#ref-for-accelerometer①②">4.5. Relative Orientation Sensor</a> <a href="#ref-for-accelerometer①③">(2)</a>
    <li><a href="#ref-for-accelerometer①④">4.5.1. Complementary filter</a> <a href="#ref-for-accelerometer①⑤">(2)</a> <a href="#ref-for-accelerometer①⑥">(3)</a> <a href="#ref-for-accelerometer①⑦">(4)</a> <a href="#ref-for-accelerometer①⑧">(5)</a> <a href="#ref-for-accelerometer①⑨">(6)</a> <a href="#ref-for-accelerometer②⓪">(7)</a>
    <li><a href="#ref-for-accelerometer②①">4.6. Gravity and Linear Acceleration Sensor</a> <a href="#ref-for-accelerometer②②">(2)</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="inertial-frame-sensor">
   <b><a href="#inertial-frame-sensor">#inertial-frame-sensor</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-inertial-frame-sensor">4.3. Absolute Orientation Sensor</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="gyroscope">
   <b><a href="#gyroscope">#gyroscope</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-gyroscope">1. Introduction</a>
    <li><a href="#ref-for-gyroscope①">4.1. Common fusion sensors</a> <a href="#ref-for-gyroscope②">(2)</a> <a href="#ref-for-gyroscope③">(3)</a> <a href="#ref-for-gyroscope④">(4)</a> <a href="#ref-for-gyroscope⑤">(5)</a>
    <li><a href="#ref-for-gyroscope⑥">4.2.2. High-pass filter</a>
    <li><a href="#ref-for-gyroscope⑦">4.3. Absolute Orientation Sensor</a>
    <li><a href="#ref-for-gyroscope⑧">4.4. Geomagnetic Orientation Sensor</a>
    <li><a href="#ref-for-gyroscope⑨">4.5. Relative Orientation Sensor</a>
    <li><a href="#ref-for-gyroscope①⓪">4.5.1. Complementary filter</a> <a href="#ref-for-gyroscope①①">(2)</a> <a href="#ref-for-gyroscope①②">(3)</a> <a href="#ref-for-gyroscope①③">(4)</a> <a href="#ref-for-gyroscope①④">(5)</a> <a href="#ref-for-gyroscope①⑤">(6)</a> <a href="#ref-for-gyroscope①⑥">(7)</a>
    <li><a href="#ref-for-gyroscope①⑦">4.6. Gravity and Linear Acceleration Sensor</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="magnetometer-magnetometers">
   <b><a href="#magnetometer-magnetometers">#magnetometer-magnetometers</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-magnetometer-magnetometers">1. Introduction</a>
    <li><a href="#ref-for-magnetometer-magnetometers①">4.1. Common fusion sensors</a> <a href="#ref-for-magnetometer-magnetometers②">(2)</a> <a href="#ref-for-magnetometer-magnetometers③">(3)</a> <a href="#ref-for-magnetometer-magnetometers④">(4)</a>
    <li><a href="#ref-for-magnetometer-magnetometers⑤">4.3. Absolute Orientation Sensor</a> <a href="#ref-for-magnetometer-magnetometers⑥">(2)</a> <a href="#ref-for-magnetometer-magnetometers⑦">(3)</a>
    <li><a href="#ref-for-magnetometer-magnetometers⑧">4.4. Geomagnetic Orientation Sensor</a>
    <li><a href="#ref-for-magnetometer-magnetometers⑨">4.6. Gravity and Linear Acceleration Sensor</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="low-pass-filter">
   <b><a href="#low-pass-filter">#low-pass-filter</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-low-pass-filter">3.1. Accelerometer</a> <a href="#ref-for-low-pass-filter①">(2)</a> <a href="#ref-for-low-pass-filter②">(3)</a>
    <li><a href="#ref-for-low-pass-filter③">4.2.2. High-pass filter</a>
    <li><a href="#ref-for-low-pass-filter④">4.5.1. Complementary filter</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="high-pass-filter">
   <b><a href="#high-pass-filter">#high-pass-filter</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-high-pass-filter">3.1. Accelerometer</a> <a href="#ref-for-high-pass-filter①">(2)</a>
    <li><a href="#ref-for-high-pass-filter②">4.5.1. Complementary filter</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="absolute-orientation-sensor">
   <b><a href="#absolute-orientation-sensor">#absolute-orientation-sensor</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-absolute-orientation-sensor">4.1. Common fusion sensors</a>
    <li><a href="#ref-for-absolute-orientation-sensor①">4.3. Absolute Orientation Sensor</a> <a href="#ref-for-absolute-orientation-sensor②">(2)</a>
    <li><a href="#ref-for-absolute-orientation-sensor③">4.4. Geomagnetic Orientation Sensor</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="geomagnetic-orientation-sensor">
   <b><a href="#geomagnetic-orientation-sensor">#geomagnetic-orientation-sensor</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-geomagnetic-orientation-sensor">4.1. Common fusion sensors</a>
    <li><a href="#ref-for-geomagnetic-orientation-sensor①">4.4. Geomagnetic Orientation Sensor</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="relative-orientation-sensor">
   <b><a href="#relative-orientation-sensor">#relative-orientation-sensor</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-relative-orientation-sensor">4.1. Common fusion sensors</a>
    <li><a href="#ref-for-relative-orientation-sensor①">4.3. Absolute Orientation Sensor</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="complementary-filter">
   <b><a href="#complementary-filter">#complementary-filter</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-complementary-filter">4.5. Relative Orientation Sensor</a> <a href="#ref-for-complementary-filter①">(2)</a>
    <li><a href="#ref-for-complementary-filter②">4.5.1. Complementary filter</a>
    <li><a href="#ref-for-complementary-filter③">4.6. Gravity and Linear Acceleration Sensor</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="linear-acceleration-sensor">
   <b><a href="#linear-acceleration-sensor">#linear-acceleration-sensor</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-linear-acceleration-sensor">3.1. Accelerometer</a>
    <li><a href="#ref-for-linear-acceleration-sensor①">4.1. Common fusion sensors</a>
    <li><a href="#ref-for-linear-acceleration-sensor②">4.6. Gravity and Linear Acceleration Sensor</a>
   </ul>
  </aside>
  <aside class="dfn-panel" data-for="gravity-sensor">
   <b><a href="#gravity-sensor">#gravity-sensor</a></b><b>Referenced in:</b>
   <ul>
    <li><a href="#ref-for-gravity-sensor">3.1. Accelerometer</a>
    <li><a href="#ref-for-gravity-sensor①">4.1. Common fusion sensors</a>
    <li><a href="#ref-for-gravity-sensor②">4.3. Absolute Orientation Sensor</a> <a href="#ref-for-gravity-sensor③">(2)</a>
   </ul>
  </aside>
<script>/* script-dfn-panel */

document.body.addEventListener("click", function(e) {
    var queryAll = function(sel) { return [].slice.call(document.querySelectorAll(sel)); }
    // Find the dfn element or panel, if any, that was clicked on.
    var el = e.target;
    var target;
    var hitALink = false;
    while(el.parentElement) {
        if(el.tagName == "A") {
            // Clicking on a link in a <dfn> shouldn't summon the panel
            hitALink = true;
        }
        if(el.classList.contains("dfn-paneled")) {
            target = "dfn";
            break;
        }
        if(el.classList.contains("dfn-panel")) {
            target = "dfn-panel";
            break;
        }
        el = el.parentElement;
    }
    if(target != "dfn-panel") {
        // Turn off any currently "on" or "activated" panels.
        queryAll(".dfn-panel.on, .dfn-panel.activated").forEach(function(el){
            el.classList.remove("on");
            el.classList.remove("activated");
        });
    }
    if(target == "dfn" && !hitALink) {
        // open the panel
        var dfnPanel = document.querySelector(".dfn-panel[data-for='" + el.id + "']");
        if(dfnPanel) {
            dfnPanel.classList.add("on");
            var rect = el.getBoundingClientRect();
            dfnPanel.style.left = window.scrollX + rect.right + 5 + "px";
            dfnPanel.style.top = window.scrollY + rect.top + "px";
            var panelRect = dfnPanel.getBoundingClientRect();
            var panelWidth = panelRect.right - panelRect.left;
            if(panelRect.right > document.body.scrollWidth && (rect.left - (panelWidth + 5)) > 0) {
                // Reposition, because the panel is overflowing
                dfnPanel.style.left = window.scrollX + rect.left - (panelWidth + 5) + "px";
            }
        } else {
            console.log("Couldn't find .dfn-panel[data-for='" + el.id + "']");
        }
    } else if(target == "dfn-panel") {
        // Switch it to "activated" state, which pins it.
        el.classList.add("activated");
        el.style.left = null;
        el.style.top = null;
    }

});
</script>